/*
 * Planta.cpp
 *
 *  Created on: 19/10/2013
 *      Author: ezequiel
 */

#include "Planta.h"
#define CANT_PUNTOS 60
Planta::Planta() {
//	   if (this->planta_vertex_buffer != NULL)
//	    {
//	        delete this->planta_vertex_buffer;
//	    }
	tiempo = 0 ;
	   this->planta_vertex_buffer_size = CANT_PUNTOS/3 *CANT_PUNTOS/3 * 3  ;
	    this->planta_vertex_buffer = new GLfloat[this->planta_vertex_buffer_size];
	    this->planta_texture_buffer = new GLfloat[this->planta_vertex_buffer_size * 2 / 3 ];
	    //
//	    if (this->planta_normal_buffer != NULL)
//	    {
//	        delete this->planta_normal_buffer;
//	    }
	    this->planta_normal_buffer_size = CANT_PUNTOS/3 *CANT_PUNTOS/3 * 3 ;
	    this->planta_normal_buffer = new GLfloat[this->planta_normal_buffer_size];

//	    if (this->planta_index_buffer != NULL)
//	    {
//	        delete this->planta_index_buffer;
//	    }
	    this->planta_index_buffer_size = 760;
	    this->planta_index_buffer = new GLuint[this->planta_index_buffer_size];
	this->pControl1 = 0;
	this->pControl2 = 0;
	this->crearForma();
	mueveIzquierda = true;
}

Planta::~Planta() {
delete this->planta_vertex_buffer;
delete this->planta_normal_buffer;
delete this->planta_index_buffer;
}

void Planta::crearForma() {


//////////////// vector de direccion //////////////
	    vector<glm::vec3> vector;
	    	glm::vec3 vect = glm::vec3(-10.0f, 0.0f , 0.0f);
	    	vector.push_back(vect);
	    	vect = glm::vec3(-5.0f, 0.0f , 0.0f);
	    	vector.push_back(vect);
	    	vect = glm::vec3(5.0f, 0.0f , 0.0f);
	    	vector.push_back(vect);
	    	vect = glm::vec3(10.0f, 0.0f , 0.0f);
	    	vector.push_back(vect);
	    	CurvaBessier* curvaBes = new CurvaBessier(vector,CANT_PUNTOS / 3 - 1 );
////////////// vector z /////////////

	    	std::vector<glm::vec3> otrov;
	    	vect = glm::vec3(0.0f, 0.0f , 5.0f);
	    	otrov.push_back(vect);
	    	vect = glm::vec3(0.0f, pControl1 , 10.0f);
	    	otrov.push_back(vect);
	    	vect = glm::vec3(0.0f, pControl1, 15.0f);
	    	otrov.push_back(vect);
	    	vect = glm::vec3(0.0f, pControl1 , 20.0f);
	    	otrov.push_back(vect);
//	       	vect = glm::vec3(18.0f, 0.0f , 0.0f);
//	    	   otrov.push_back(vect);
	    	CurvaBessier* curvaBes2 = new CurvaBessier(otrov,CANT_PUNTOS / 3 - 1 );
//	    	CurvaSpline* curvaBes2 = new CurvaSpline(otrov, CANT_PUNTOS / 3 - 1);

	    	this->alturaPlanta = CANT_PUNTOS / 3 - 1;
////////////// curva grosor ////////////////


	    	std::vector<glm::vec3> vecGrosor;
	    	vect = glm::vec3(5.0f, 0.0f , 0.0f);
	    	vecGrosor.push_back(vect);
	    	vect = glm::vec3(10.0f, 0.37f , 0.0f);
	    	vecGrosor.push_back(vect);
	    	vect = glm::vec3(15.0f, 0.43f , 0.0f);
	    	vecGrosor.push_back(vect);
	    	vect = glm::vec3(20.0f, 0.0f , 0.0f);
	    	vecGrosor.push_back(vect);
	    	CurvaBessier* curvaGrosor = new CurvaBessier(vecGrosor,CANT_PUNTOS / 3 - 1 );





	    	/////////////// declaracion de vectores ////////////

	    	otrov = curvaBes2->obtenerPuntos();
	    	vector = curvaBes->obtenerPuntos();
	    	vecGrosor = curvaGrosor->obtenerPuntos();
	    	delete curvaBes2;
	    	delete curvaBes;
	    	delete curvaGrosor;

	    	 float pasoU = 0;
	    	float pasoV = 0.0;
	    	int p = 0;

	    	int j ;
	    	for (int k = 0 ; k < CANT_PUNTOS / 3 ; k++){
	    	j = 0;
	    	pasoU = 0.0;
	    	pasoV = pasoV + 0.05;
	    	for(int i = k * CANT_PUNTOS;i < (k+1) * CANT_PUNTOS; i = i + 3)
	    	{
	    		this->planta_vertex_buffer[i] = (vector[j].x  + otrov[k].x) * vecGrosor[k].y  ;
	    		this->planta_vertex_buffer[i+1] = ( vector[j].y + otrov[k].y )   ;
	    		this->planta_vertex_buffer[i+2] = (vector[j].z  + otrov[k].z) ;
	    		this->planta_texture_buffer[p] = pasoU;
	    		p++;
	    		 this->planta_texture_buffer[p] = pasoV;
	    		p++;
	    		pasoU = pasoU + 0.05 ;
	    		this->planta_normal_buffer[i] = 0.1f;
	    		this->planta_normal_buffer[i+1] = 0.1f;
	    		this->planta_normal_buffer[i+2] = 0.1f;
//	    		this->planta_index_buffer[i] = j + k* CANT_PUNTOS/3;
//	    		this->planta_index_buffer[i+1] = j + k* CANT_PUNTOS/3 ;
//	    		this->planta_index_buffer[i+2] = j + k* CANT_PUNTOS/3;
	    		j++;

	    	}
	    	}
//	    	this->calcularNormales();
	    	this->indexarPuntos();
//	    	this->indexar();



}

void Planta::render(GLuint handle, glm::mat4* matModelo) {
	// Normal Matrix
//	this->crearForma();
	this->renderMatrix(handle, &this->proyeccion);
	glBindTexture (GL_TEXTURE_2D, this->textureid);
		    glm::mat3 normal_matrix = glm::mat3 ( 1.0f );

		    // Bind Normal MAtrix
		    GLuint location_normal_matrix = glGetUniformLocation(handle, "NormalMatrix");
		    if( location_normal_matrix >= 0 )
			{
		        glUniformMatrix3fv( location_normal_matrix, 1, GL_FALSE, &normal_matrix[0][0]);
			}

		    // Bind Model Matrix
		    GLuint location_model_matrix = glGetUniformLocation( handle, "ModelMatrix");
		    if( location_model_matrix >= 0 )
			{
				glUniformMatrix4fv( location_model_matrix, 1, GL_FALSE,&((*matModelo)[0][0]));
			}

		    int loc = glGetUniformLocation(handle, "Tex1");
		        				    if( loc >= 0 )
		        				    {
		        						// We indicate that Uniform Variable sampler2D "text" uses  Texture Unit 0
		        				        glUniform1i(loc, 0);
		        				    }
		        				    else
		        				    {
		        				        fprintf(stderr, "Uniform variable Tex1 not found!\n");
		        				    }

		    // Bind tiempo para variación de movimiento
	    	GLuint wave_loc = glGetUniformLocation(handle, "TIEMPO");
	    				    tiempo = tiempo + 1;
	    				    if( wave_loc >= 0 )
	    					{
	    				    	glUniform1f( wave_loc, tiempo);
	    					}

		    glEnableClientState(GL_VERTEX_ARRAY);
			glEnableClientState(GL_NORMAL_ARRAY);
			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
			glVertexPointer(3, GL_FLOAT, 0, planta_vertex_buffer);
			glNormalPointer(GL_FLOAT, 0, planta_normal_buffer);
			glTexCoordPointer(2, GL_FLOAT, 0, planta_texture_buffer);
		    glDrawElements(GL_TRIANGLE_STRIP, this->planta_index_buffer_size, GL_UNSIGNED_INT, this->planta_index_buffer);
		    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		    glDisableClientState(GL_VERTEX_ARRAY);
		    glDisableClientState(GL_NORMAL_ARRAY);

//	    	delete this->planta_vertex_buffer;
//		    	delete this->planta_normal_buffer;
//		    	delete this->planta_index_buffer;
}

void Planta::moverPlanta() {
//	if(mueveIzquierda){
//		this->pControl1 -= 0.05;
//		this->pControl2 -= 0.05;}
//	if(!mueveIzquierda){
//		this->pControl1 += 0.05;
//	this->pControl2 += 0.05;}
//	if (pControl1 <= -3)
//		mueveIzquierda = false;
//	if (pControl1 >= 3)
//		mueveIzquierda = true;



}

void Planta::indexarPuntos() {

	int malla[20][20];

		        int e = 0;
		        for(int m = 0; m < 20; m++)
		                for(int n = 0; n < 20; n++)
		                        malla[m][n] = e++;


		        int sentido = 1;
		        int k = 0;

		        for(int i=0; i < (19); i++)
		        {
		                if(sentido == 1)
		                {
		                        for(int j=0; j <= (19); j++) {
		                                this->planta_index_buffer[k++] = malla[i][j];
		                                this->planta_index_buffer[k++] = malla[i+1][j];
		                        }

		                        sentido = -1;
		                }
		                else if(sentido == -1)
		                {
		                        for(int j=(19); j >= 0; j--) {
		                                this->planta_index_buffer[k++] = malla[i][j];
		                                this->planta_index_buffer[k++] = malla[i+1][j];
		                        }

		                        sentido = 1;
		                }
		        }

	        }

void Planta::indexar() {
//	planta_index_buffer[0] = 0;
//	planta_index_buffer[1] = 0;
//	planta_index_buffer[2] = 0;
//
//	planta_index_buffer[3] = 2;
//	planta_index_buffer[4] = 2;
//	planta_index_buffer[5] = 2;
//
//	planta_index_buffer[6] = 4;
//	planta_index_buffer[7] = 4;
//	planta_index_buffer[8] = 4;
//
//	planta_index_buffer[9] = 6;
//	planta_index_buffer[10] = 6;
//	planta_index_buffer[11] = 6;
//
//	planta_index_buffer[12] = 8;
//	planta_index_buffer[13] = 8;
//	planta_index_buffer[14] = 8;
//
//	planta_index_buffer[15] = 10;
//	planta_index_buffer[16] = 10;
//	planta_index_buffer[17] = 10;
//
//
//
///////////// fin primera linea ///////////
//
//	planta_index_buffer[18] = 1;
//	planta_index_buffer[19] = 1;
//	planta_index_buffer[20] = 1;
//
//	planta_index_buffer[21] = 3;
//	planta_index_buffer[22] = 3;
//	planta_index_buffer[23] = 3;
//
//	planta_index_buffer[24] = 5;
//	planta_index_buffer[25] = 5;
//	planta_index_buffer[26] = 5;
//
//	planta_index_buffer[27] = 7;
//	planta_index_buffer[28] = 7;
//	planta_index_buffer[29] = 7;
//
//	planta_index_buffer[30] = 9;
//	planta_index_buffer[31] = 9;
//	planta_index_buffer[32] = 9;
//
//	planta_index_buffer[33] = 11;
//	planta_index_buffer[34] = 11;
//	planta_index_buffer[35] = 11;

//planta_index_buffer = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36};


}

void Planta::calcularNormales() {
//	for(int i = 0; i < CANT_PUNTOS / 3 ; i++)
//	{
//		for (int k = 0 ; k < CANT_PUNTOS / 3; k += 3)
//		{
//			this->planta_normal_buffer[k+i*CANT_PUNTOS] = 0.5f;
//			    		this->planta_normal_buffer[k+i*CANT_PUNTOS] = 0.5f;
//			    		this->planta_normal_buffer[k+i*CANT_PUNTOS] = 0.5f;
//		}
//		for (int k = CANT_PUNTOS ; k < 2* CANT_PUNTOS / 3; k += 3)
//		{
//			this->planta_normal_buffer[k+1+i*CANT_PUNTOS / 3] = 0.5f;
//			    		this->planta_normal_buffer[k+1+i*CANT_PUNTOS] = 0.5f;
//			    		this->planta_normal_buffer[k+1+i*CANT_PUNTOS] = 0.5f;
//		}
//		for (int k = 2*CANT_PUNTOS ; k < 3* CANT_PUNTOS / 3; k += 3)
//		{
//			this->planta_normal_buffer[k+i*CANT_PUNTOS / 3] = 0.8f;
//			    		this->planta_normal_buffer[k+2+i*CANT_PUNTOS ] = 0.6f;
//			    		this->planta_normal_buffer[k+2+i*CANT_PUNTOS] = 0.9f;
//		}
//	}

	glm::vec3 vecResult;
	glm::vec3 vec1;
	glm::vec3 vec2;

for (int k = 0 ; k < 19 ; k++){
	for (int i = k * CANT_PUNTOS  ; i < k * CANT_PUNTOS  + CANT_PUNTOS ; i = i +3 )
	{
		vec1.x = planta_vertex_buffer[i] - planta_vertex_buffer[i+6*CANT_PUNTOS];
		vec1.y = planta_vertex_buffer[i+1] - planta_vertex_buffer[i+6*CANT_PUNTOS+1];
		vec1.z = planta_vertex_buffer[i+2] - planta_vertex_buffer[i+6*CANT_PUNTOS+2];
		vec2.x = planta_vertex_buffer[i] - planta_vertex_buffer[i+3];
		vec2.y = planta_vertex_buffer[i+1] -planta_vertex_buffer[i+4];
		vec2.z = planta_vertex_buffer[i+2] -planta_vertex_buffer[i+5];
		vecResult = calcularNormal(vec1, vec2);
		planta_normal_buffer[i] = vecResult.x;
		planta_normal_buffer[i+1] = vecResult.y;
		planta_normal_buffer[i+2] = vecResult.z;

	}
}

}

void Planta::setearMovPlanta(float float1) {
	this->pControl1 = float1;
}

glm::vec3 Planta::calcularNormal(glm::vec3 vec1, glm::vec3 vec2)
{
	glm::vec3 retorno;
	retorno.x = vec1.y * vec2.z - vec1.z * vec2.y;
	retorno.y = vec1.z * vec2.x - vec1.x * vec2.z;
	retorno.z =vec1.x * vec2.y - vec1.y * vec2.x;


	return retorno;

}

void Planta::render(GLuint handle) {
}
